import { Vue } from './install';

const forEach = (obj, callback) => {
  Object.keys(obj).forEach(key => {
    callback && callback(key, obj[key]);
  });
};

class Store {
  constructor(options) {

    // 用户的 state
    const state = options.state;

    this.getters = {};
    // 用户的 getters
    const getters = options.getters;
    // 把 getters 放在 state 上不友好，每取一次就执行一次，消耗性能，因此，把 getter 定义到 compunted 来处理，他有缓存作用
    // forEach(getters, (getterKey, getterValue) => {
    //   Object.defineProperty(this.getters, getterKey, {
    //     get: () => {
    //       return getterValue.call(this, this.state);
    //     }
    //   });
    // });
    const computed = {};
    forEach(getters, (getterKey, getterValue) => {
      // 把 getters 的相关属性作为计算属性处理，有缓存作用，防止多次取值时消耗性能。
      computed[getterKey] = () => {
        return getterValue.call(this, this.state);
      };

      Object.defineProperty(this.getters, getterKey, {
        get: () => this.vm[getterKey],
      });
    });


    this.vm = new Vue({
      data: {
        $$state: state  // vue 内部处理了 $不被代理所以 使用 $$
      },
      computed
    });

    this.mutations = {};
    // 用户的 mutations
    const mutations = options.mutations;
    forEach(mutations, (mutationKey, mutationValue) => {
      this.mutations[mutationKey] = (payload) => mutationValue(this.state, payload);
    });

    this.actions = {};
    // 用户的 mutations
    const actions = options.actions;
    forEach(actions, (actionKey, actionValue) => {
      this.actions[actionKey] = (payload) => actionValue(this, payload);
    });

  }

  // commit 挂载到 $store 上供用户调用， $store.commit("xxx", payload)
  commit = (mutationKey, payload) => {
    this.mutations[mutationKey](payload);
  }

  // dispatch 挂载到 $store 上供用户调用， $store.dispatch("xxx", payload)
  dispatch = (actionKey, payload) => {
    this.actions[actionKey](payload);
  }

  get state() {
    // 通过中间层获取用户的 state
    return this.vm._data.$$state;
  }

}

export default Store;